<!DOCTYPE html>
<html>
<head hexo-theme='https://volantis.js.org/#'>
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
    
  
  <!-- 渲染优化 -->
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="baidu-site-verification" content="hZiKlANZ5f" />
  <!-- 页面元数据 -->
  
    <title>mysql数据库笔记 - CyChan&#39;s Blog</title>
  
    <meta name="keywords" content="MySQL">
  
  
    <meta name="description" content="1.事务的ACID特性原子性(A)一个事务要么全部提交成功，要么全部失败回滚，不能只执行其中的一部分操作，这就是事务的原子性">
  

  <!-- feed -->
  
    <link rel="alternate" href="/atom.xml" title="CyChan's Blog">
  

  <!-- import meta -->
  

  <!-- link -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.13/css/all.min.css">
  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css">

  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.css">

  

  
  <link rel="shortcut icon" type='image/x-icon' href="https://gitee.com/CyChan811/BlogImage/raw/master/img/头像.jpg">
  

  
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.css">
  

  

  <!-- import link -->
  

  
  
    
<link rel="stylesheet" href="/css/style.css">

  

  <script>
    function setLoadingBarProgress(num) {
      document.getElementById('loading-bar').style.width=num+"%";
    }
  </script>

  
  
</head>

<body>
  
  <div id="loading-bar-wrapper">
  <div id="loading-bar"></div>
</div>
<header class="l_header shadow blur">
  <div class='container'>
  <div class='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h'>
        <li><a class="s-comment fas fa-comments fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
          <li><a class="s-toc fas fa-list fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
          
          
            CyChan
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h'>
          
          
          
            
            
              <li>
                <a class="flat-box" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fas fa-home fa-fw'></i>首页
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/Message/
                  
                  
                  
                    id="Message"
                  >
                  <i class='fas fa-comments fa-fw fa-fw'></i>留言板
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>

      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fas fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>

			<ul class='switcher nav-list-h'>
				
					<li><a class="s-search fas fa-search fa-fw" target="_self" href='javascript:void(0)'></a></li>
				
				<li>
          <a class="s-menu fas fa-bars fa-fw" target="_self" href='javascript:void(0)'></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="flat-box" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fas fa-home fa-fw'></i>首页
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/Message/
                  
                  
                  
                    id="Message"
                  >
                  <i class='fas fa-comments fa-fw fa-fw'></i>留言板
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>
		</div>
	</div>
  </div>
</header>

<script>setLoadingBarProgress(40);</script>



  <div class="l_body nocover">
    <div class='body-wrapper'>
      

<div class='l_main'>
  

  
    <article id="post" class="post white-box reveal shadow article-type-post" itemscope itemprop="blogPost">
      


  <section class='meta'>
    
      
      
      <div class="meta" id="header-meta">
        
          
  <h1 class="title">
    <a href="/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/">
      mysql数据库笔记
    </a>
  </h1>


        
        <div class='new-meta-box'>
          
            
          
            
              
<div class='new-meta-item author'>
  <a href="https://cychan811.gitee.io" rel="nofollow">
    <img src="https://gitee.com/CyChan811/BlogImage/raw/master/img/头像.jpg">
    <p>CyChan</p>
  </a>
</div>

            
          
            
              
  
  <div class='new-meta-item category'>
    <a href='/categories/%E5%90%8E%E5%8F%B0/' rel="nofollow">
      <i class="fas fa-folder-open fa-fw" aria-hidden="true"></i>
      <p>后台</p>
    </a>
  </div>


            
          
            
              <div class="new-meta-item date">
  <a class='notlink'>
    <i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i>
    <p>发布于：2021年1月31日</p>
  </a>
</div>

            
          
            
              

            
          
            
              
  <div class="new-meta-item browse valine">
    <a class='notlink'>
      <i class="fas fa-eye fa-fw" aria-hidden="true"></i>
      
      <span id="/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/" class="leancloud_visitors" data-flag-title="mysql数据库笔记">
      <p>
        <span class="leancloud-visitors-count"></span>
      </p>
      </span>
    </a>
  </div>


            
          
        </div>
        
          <hr>
        
      </div>
    
  </section>


      <section class="article typo">
        <div class="article-entry" itemprop="articleBody">
          
          
          <h2 id="1-事务的ACID特性"><a href="#1-事务的ACID特性" class="headerlink" title="1.事务的ACID特性"></a>1.事务的ACID特性</h2><h3 id="原子性-A"><a href="#原子性-A" class="headerlink" title="原子性(A)"></a>原子性(A)</h3><p>一个事务要么全部提交成功，要么全部失败回滚，不能只执行其中的一部分操作，这就是事务的原子性</p>
<a id="more"></a>

<h3 id="一致性-C"><a href="#一致性-C" class="headerlink" title="一致性(C)"></a>一致性(C)</h3><p>保证事务只能把数据库从一个有效（正确）的状态“转移”到另一个有效（正确）的状态。</p>
<p>有效（正确）状态是指满足我们给数据库定义的一些规则（约束条件），就是当前的状态满足预定的约束就叫做正确的状态</p>
<h3 id="隔离性-I"><a href="#隔离性-I" class="headerlink" title="隔离性(I)"></a>隔离性(I)</h3><p>事务的隔离性是指在并发环境中，并发的事务时相互隔离的，一个事务的执行不能被其他事务干扰。不同的事务并发操作相同的数据时，每个事务都有各自完成的数据空间，即一个事务内部的操作及使用的数据对其他并发事务时隔离的，并发执行的各个事务之间不能相互干扰。</p>
<p><strong>隔离级别（由低到高）:</strong></p>
<ol>
<li><code>read uncommitted;</code>(读未提交的)</li>
<li><code>read committed;</code>(读已经提交的)</li>
<li><code>repeatable read;</code>(可以重复读)</li>
<li><code>serializable;</code>(串行化)</li>
</ol>
<h3 id="持久性-D"><a href="#持久性-D" class="headerlink" title="持久性(D)"></a>持久性(D)</h3><p>一旦事务提交，那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。–即使发生系统崩溃或机器宕机等故障，只要数据库能够重新启动，那么一定能够将其恢复到事务成功结束的状态</p>
<h3 id="注意："><a href="#注意：" class="headerlink" title="注意："></a>注意：</h3><p><strong>事务具备ACID里C的特性是说通过事务的AID来保证我们的一致性.</strong></p>
<h2 id="2-隔离级别"><a href="#2-隔离级别" class="headerlink" title="2.隔离级别"></a>2.隔离级别</h2><h4 id="事务的并发问题"><a href="#事务的并发问题" class="headerlink" title="事务的并发问题"></a>事务的并发问题</h4><ol>
<li><strong>脏读：</strong> A事务读取B事务尚未提交的数据，此时如果B事务发生错误并执行回滚操作，那么A事务读取到的数据就是脏数据。</li>
<li><strong>不可重复读</strong>：事务A多次读取同一数据，事务B在事务A多次读取的过程中，对数据作了更新并提交，导致事务A多次读取同一数据时，结果 不一致。</li>
<li><strong>幻读：</strong> 指当用户读取某一范围的数据行时，另一个事务又在该范围内插入了新行，当用户再读取该范围的数据行时，会发现有新的“幻影”。</li>
</ol>
<p><strong>注意：</strong> 不可重复读侧重于<strong>修改</strong>，幻读侧重于<strong>新增或删除</strong>。解决不可重复读的问题只需锁住满足条件的行，解决幻读需要next-key lock(行锁+间隙锁)</p>
<h4 id="Read-Uncommitted（读取未提交内容）"><a href="#Read-Uncommitted（读取未提交内容）" class="headerlink" title="Read Uncommitted（读取未提交内容）"></a>Read Uncommitted（读取未提交内容）</h4><p>在该隔离级别，所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用，因为它的性能也不比其他级别好多少。读取未提交的数据，也被称之为脏读（Dirty Read）。</p>
<h4 id="Read-Committed（读取提交内容）"><a href="#Read-Committed（读取提交内容）" class="headerlink" title="Read Committed（读取提交内容）"></a>Read Committed（读取提交内容）</h4><p>这是大多数数据库系统的默认隔离级别（但不是MySQL默认的）。它满足了隔离的简单定义：一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读（Nonrepeatable Read），因为同一事务的其他实例在该实例处理其间可能会有新的commit，所以同一select可能返回不同结果。</p>
<h4 id="Repeatable-Read（可重复读）"><a href="#Repeatable-Read（可重复读）" class="headerlink" title="Repeatable Read（可重复读）"></a>Repeatable Read（可重复读）</h4><p>这是MySQL的默认事务隔离级别，它确保同一事务的多个实例在并发读取数据时，会看到同样的数据行。不过理论上，这会导致另一个棘手的问题：幻读 （Phantom Read）。简单的说，幻读指当用户读取某一范围的数据行时，另一个事务又在该范围内插入了新行，当用户再读取该范围的数据行时，会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制（MVCC，Multiversion Concurrency Control）机制解决了该问题。</p>
<h4 id="Serializable（串行化）"><a href="#Serializable（串行化）" class="headerlink" title="Serializable（串行化）"></a>Serializable（串行化）</h4><p>这是最高的隔离级别，它通过强制事务排序，使之不可能相互冲突，从而解决幻读问题。简言之，它是在每个读的数据行上加上共享锁。在这个级别，可能导致大量的超时现象和锁竞争。</p>
<h2 id="3-范式"><a href="#3-范式" class="headerlink" title="3.范式"></a>3.范式</h2><h4 id="第一范式"><a href="#第一范式" class="headerlink" title="第一范式"></a>第一范式</h4><p>第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值，就说明该数据库表满足了第一范式。</p>
<h4 id="第二范式"><a href="#第二范式" class="headerlink" title="第二范式"></a>第二范式</h4><p>第二范式在第一范式的基础之上更进一层。<strong>第二范式需要确保数据库表中的每一列都和主键相关，而不能只与主键的某一部分相关（主要针对联合主键而言）。</strong> 也就是说在一个数据库表中，一个表中只能保存一种数据，不可以把多种数据保存在同一张数据库表中。</p>
<p>若某关系R属于第一范式，且<strong>每一个非主属性完全函数依赖于任何一个候选码</strong>，则关系R属于第二范式。</p>
<h4 id="第三范式"><a href="#第三范式" class="headerlink" title="第三范式"></a>第三范式</h4><p>第三范式需要确保数据表中的每一列数据都和主键直接相关，而不能间接相关。</p>
<p>3NF在2NF的基础之上，消除了非主属性对于码的传递函数依赖，即非主属性既不传递依赖于码，也不部分依赖于码。</p>
<h2 id="4-聚集索引和非聚集索引、二级索引"><a href="#4-聚集索引和非聚集索引、二级索引" class="headerlink" title="4.聚集索引和非聚集索引、二级索引"></a>4.聚集索引和非聚集索引、二级索引</h2><p>聚簇索引的叶子节点就是数据节点，聚簇索引的顺序就是数据的物理存储顺序，而非聚簇索引的叶子节点仍然是索引节点，只不过有指向对应数据块的指针。</p>
<p>聚集索引：InnoDB</p>
<ul>
<li>对于聚集索引，<strong>叶子结点即存储了真实的数据行</strong>。聚簇索引中的每个叶子节点包含主键值、事务ID、回滚指针(rollback pointer用于事务和MVCC）和余下的列，</li>
</ul>
<p>非聚集索引：MYISAM</p>
<ul>
<li>MYISAM是按列值与行号来组织索引的。<strong>它的叶子节点中保存的实际上是指向存放数据的物理块的指针。</strong></li>
<li>从MYISAM存储的物理文件我们能看出，MYISAM引擎的索引文件（.MYI）和数据文件(.MYD)是相互独立的。</li>
</ul>
<p>二级索引：</p>
<ul>
<li>在InnoDb中，强制使用主键作为聚簇索引，B+ Tree叶子节点存储就是主键数据，而二级索引的叶子节点存储的是主键的键值；</li>
<li>在MyISAM中，主键索引与二级索引没什么区别，都是存储的数据行对应的地址。</li>
</ul>
<h2 id="5-InnoDB为什么使用B-树做索引而不是使用B树"><a href="#5-InnoDB为什么使用B-树做索引而不是使用B树" class="headerlink" title="5.InnoDB为什么使用B+树做索引而不是使用B树"></a>5.InnoDB为什么使用B+树做索引而不是使用B树</h2><ol>
<li><p><strong>B+树的磁盘读写代价更低</strong>：B+树的内部节点并没有指向关键字具体信息的指针，因此其内部节点相对B树更小，如果把所有同一内部节点的关键字存放在同一盘块中，那么盘块所能容纳的关键字数量也越多，一次性读入内存的需要查找的关键字也就越多，相对IO读写次数就降低了。（一个节点代表一个数据块，就需要一次磁盘I/O，所以层数越少，磁盘I/O次数就越少）</p>
</li>
<li><p><strong>B+树的查询效率更加稳定</strong>：由于非终结点并不是最终指向文件内容的结点，而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同，导致每一个数据的查询效率相当。</p>
</li>
<li><p><strong>B+树适合范围查找:</strong> 由于B+树的数据都存储在叶子结点中，分支结点均为索引，方便扫库，只需要扫一遍叶子结点即可，但是B树因为其分支结点同样存储着数据，我们要找到具体的数据，需要进行一次中序遍历按序来扫，所以B+树更加适合在区间查询的情况，所以通常B+树用于数据库索引。</p>
</li>
</ol>
<h2 id="6-为什么推荐自增id作为主键，而不是自建主键？"><a href="#6-为什么推荐自增id作为主键，而不是自建主键？" class="headerlink" title="6.为什么推荐自增id作为主键，而不是自建主键？"></a>6.为什么推荐自增id作为主键，而不是自建主键？</h2><p>B+树为了维护索引的有序性，每插入或者删除更新一条记录的时候，都需要对索引进行更新。</p>
<ul>
<li>如果是自建索引，则很有可能在随机中间部分进行插入，这就可能造成页分裂，从而进行调整，这是会导致性能下降的，如果是大量的页分裂，就会导致性能急剧下降。</li>
<li>如果使用的是自增id作为主键，由于插入的表中生成的id比索引中的id都大，所以它要么合成到已存在的结点（元素个数未满），要么放入新建的结点中，所以就不存在页分裂了。而且按这种方式存储就能提升页面的最大填充率，不会有页的浪费。</li>
</ul>
<h2 id="7-主键索引和普通索引，以及它们之间的区别"><a href="#7-主键索引和普通索引，以及它们之间的区别" class="headerlink" title="7.主键索引和普通索引，以及它们之间的区别"></a>7.主键索引和普通索引，以及它们之间的区别</h2><p>主键索引和非主键索引的区别是：非主键索引的叶子节点存放的是<strong>主键的值</strong>，而主键索引的叶子节点存放的是<strong>整行数据</strong>，其中非主键索引也被称为<strong>二级索引</strong>，而主键索引也被称为<strong>聚簇索引</strong>。</p>
<h2 id="8-索引下推"><a href="#8-索引下推" class="headerlink" title="8.索引下推"></a>8.索引下推</h2><p>在联合索引中，在支持索引下推(ICP)优化后，MySQL会在取出索引回表的同时，判断是否可以进行where条件过滤再进行索引查询，也就是说提前执行where的部分过滤操作。</p>
<h2 id="9-覆盖索引、联合索引"><a href="#9-覆盖索引、联合索引" class="headerlink" title="9.覆盖索引、联合索引"></a>9.覆盖索引、联合索引</h2><p><strong>联合索引：</strong> 对多个字段同时建立的索引(有顺序，ABC，ACB是完全不同的两种联合索引。)</p>
<p><strong>覆盖索引：</strong> SQL只需要通过索引就可以返回查询所需要的数据，而<strong>不必通过二级索引查到主键之后再去查询数据。</strong> sql语句的所求查询字段（select列）和查询条件字段（where子句）全都包含在一个索引中（联合索引），可以直接使用索引查询而不需要回表。这就是覆盖索引。</p>
<h2 id="10-为什么用-B-树做索引而不用哈希表做索引？"><a href="#10-为什么用-B-树做索引而不用哈希表做索引？" class="headerlink" title="10.为什么用 B+ 树做索引而不用哈希表做索引？"></a>10.为什么用 B+ 树做索引而不用哈希表做索引？</h2><ol>
<li>哈希表是把索引字段映射成对应的哈希码然后再存放在对应的位置，这样的话，如果我们要进行模糊查找的话，显然哈希表这种结构是不支持的，只能遍历这个表。而B+树则可以通过最左前缀原则快速找到对应的数据。</li>
<li>如果我们要进行范围查找，例如查找ID为100 ~ 400的人，哈希表同样不支持，只能遍历全表。</li>
<li>索引字段通过哈希映射成哈希码，如果很多字段都刚好映射到相同值的哈希码的话，那么形成的索引结构将会是一条很长的链表，这样的话，查找的时间就会大大增加。</li>
</ol>
<h2 id="11-SQL注入漏洞产生的原因，如何防止？"><a href="#11-SQL注入漏洞产生的原因，如何防止？" class="headerlink" title="11.SQL注入漏洞产生的原因，如何防止？"></a>11.SQL注入漏洞产生的原因，如何防止？</h2><h4 id="原因："><a href="#原因：" class="headerlink" title="原因："></a>原因：</h4><ol>
<li>程序编写者在处理应用程序和数据库交互时，使用字符串拼接的方式构造SQL语句。</li>
<li>Web应用程序的开发人员对用户所输入的数据或cookie等内容不进行过滤或验证(即存在注入点)就直接传输给数据库，就可能导致拼接的SQL被执行，获取对数据库的信息以及提权，发生SQL注入攻击。</li>
</ol>
<h4 id="防止措施："><a href="#防止措施：" class="headerlink" title="防止措施："></a>防止措施：</h4><ol>
<li>分级管理<ul>
<li>对用户进行分级管理，严格控制用户的权限，对于普通用户，禁止给予数据库建立、删除、修改等相关权限，只有系统管理员才具有增、删、改、查的权限。</li>
</ul>
</li>
<li>采用预编译，用set方法传值（简单又有效），而不用字符串拼接的方法；</li>
<li>使用正则表达式过滤传入的参数（or，union等）；</li>
<li>字符串过滤（insert，delete，select等）</li>
<li>避免直接向用户显示数据库错误，攻击者可以使用这些错误消息来获取有关数据库的信息。</li>
</ol>
<h2 id="12-explain之type"><a href="#12-explain之type" class="headerlink" title="12.explain之type"></a>12.explain之type</h2><p>结果值从好到坏：<br>system &gt; const &gt; eq_ref &gt; ref &gt; range &gt; index &gt; ALL</p>
<p><strong>一般来说， 我们需要保证查询至少达到 range 级别， 最好达到ref 。</strong></p>
<h2 id="13-为什么MyISAM会比Innodb的查询速度快"><a href="#13-为什么MyISAM会比Innodb的查询速度快" class="headerlink" title="13.为什么MyISAM会比Innodb的查询速度快"></a>13.为什么MyISAM会比Innodb的查询速度快</h2><p><strong>INNODB在做SELECT的时候，要维护的东西比MYISAM引擎多很多:</strong></p>
<ol>
<li>INNODB要缓存数据块，MYISAM只缓存索引块，  这中间还有换进换出的减少；</li>
<li>innodb寻址要映射到块，再到行，MYISAM记录的直接是文件的OFFSET，定位比INNODB要快</li>
<li>INNODB还需要维护MVCC一致；虽然你的场景没有，但他还是需要去检查和维护MVCC (Multi-Version Concurrency Control)多版本并发控制 </li>
</ol>
<h2 id="14-缓存数据库和远程数据库怎么实现同步？"><a href="#14-缓存数据库和远程数据库怎么实现同步？" class="headerlink" title="14.缓存数据库和远程数据库怎么实现同步？"></a>14.缓存数据库和远程数据库怎么实现同步？</h2><ul>
<li>读的时候，先读缓存，缓存没有的话，就读数据库，然后取出数据后放入缓存，同时返回响应。</li>
<li>更新的时候，先更新数据库，然后再<strong>删除</strong>缓存。</li>
</ul>
<p>了解更多→ <a href="https://zhuanlan.zhihu.com/p/147028497" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/147028497</a></p>
<h2 id="15-mysql-innodb引擎什么时候表锁，什么时候行锁？"><a href="#15-mysql-innodb引擎什么时候表锁，什么时候行锁？" class="headerlink" title="15.mysql innodb引擎什么时候表锁，什么时候行锁？"></a>15.mysql innodb引擎什么时候表锁，什么时候行锁？</h2><h4 id="InnoDB基于索引的行锁"><a href="#InnoDB基于索引的行锁" class="headerlink" title="InnoDB基于索引的行锁"></a>InnoDB基于索引的行锁</h4><ul>
<li>InnoDB行锁是<strong>通过索引上的索引项</strong>来实现的，这一点ＭySQL与Oracle不同，后者是通过在数据中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味者：<strong>只有通过索引条件检索数据，InnoDB才会使用行级锁，否则，InnoDB将使用表锁</strong></li>
<li>在MySQL中，<strong>行级锁并不是直接锁记录，而是锁索引</strong>。索引分为主键索引和非主键索引两种，如果一条sql语句操作了主键索引，MySQL就会锁定这条主键索引；如果一条语句操作了<strong>非主键索引，MySQL会先锁定该非主键索引，再锁定相关的主键索引</strong>。 在UPDATE、DELETE操作时，MySQL不仅锁定WHERE条件扫描过的所有索引记录，而且会锁定相邻的键值，即所谓的next-key locking。</li>
</ul>
<h4 id="行锁变表锁的情况："><a href="#行锁变表锁的情况：" class="headerlink" title="行锁变表锁的情况："></a>行锁变表锁的情况：</h4><ul>
<li>导致这个的原因第一是sql语句写法问题，<strong>没有合理构建和使用索引</strong>。如果不通过索引条件检索数据，那么InnoDB将对表中的所有记录加锁，实际效果跟表锁一样。</li>
<li>第二个原因是<strong>mysql的优化器</strong>，有时优化器发现：即使使用了索引，还是要做全表扫描，故而放弃了索引，也就没有使用行锁，却使用了表锁</li>
</ul>
<h2 id="16-行锁、间隙锁和next-key锁"><a href="#16-行锁、间隙锁和next-key锁" class="headerlink" title="16.行锁、间隙锁和next-key锁"></a>16.行锁、间隙锁和next-key锁</h2><h4 id="行锁"><a href="#行锁" class="headerlink" title="行锁"></a>行锁</h4><p>单条索引记录上加锁，record lock<strong>锁住的永远是索引，而非记录本身</strong>，即使该表上没有任何索引，那么innodb会在后台创建一个隐藏的聚集主键索引，那么锁住的就是这个隐藏的聚集主键索引。</p>
<h4 id="间隙锁"><a href="#间隙锁" class="headerlink" title="间隙锁"></a>间隙锁</h4><p><strong>在索引记录之间的间隙中加锁</strong>，或者是在某一条索引记录之前或者之后加锁，并<strong>不包括该索引记录本身</strong>。(范围查询的时候会用，等值查询的时候不需要)</p>
<h4 id="next-key锁"><a href="#next-key锁" class="headerlink" title="next-key锁"></a>next-key锁</h4><p>next-key锁其实包含了记录锁和间隙锁，即锁定一个范围，并且锁定记录本身，<strong>InnoDB默认加锁方式是next-key 锁。</strong></p>
<h4 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h4><ul>
<li>间隙锁和next-key锁是Innodb<strong>在可重复读隔离级别下为了解决幻读问题</strong>时引入的锁机制</li>
<li>行锁是为了解决不可重复读（针对更新）的问题，而间隙锁是为了解决幻读（针对插入和删除）的问题</li>
</ul>
<h2 id="17-mysql日志"><a href="#17-mysql日志" class="headerlink" title="17.mysql日志"></a>17.mysql日志</h2><p>在 MySQL 中，有 4 种不同的日志，分别是错误日志、二进制日志<br>（BINLOG 日志）、查询日志和慢查询日志</p>
<h4 id="（1）错误日志"><a href="#（1）错误日志" class="headerlink" title="（1）错误日志"></a>（1）错误日志</h4><p>错误日志是 MySQL 中最重要的日志之一，它记录了当 mysqld 启动和停止时，以及服务器在运行过程中发生任何<br>严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时，可以首先查看此日志。</p>
<h4 id="（2）二进制日志"><a href="#（2）二进制日志" class="headerlink" title="（2）二进制日志"></a>（2）二进制日志</h4><p>二进制日志（BINLOG）记录了所有的 <strong>增删改操作</strong>，但是<strong>不包括数据查询语句</strong>。此日志对于灾难时的数据恢复起着极其重要的作用，<strong>MySQL的主从复制， 就是通过该binlog实现的。</strong></p>
<p>从底层原理来说，binlog有三个模式：</p>
<ol>
<li>statement<ul>
<li>该日志格式在日志文件中<strong>记录的都是SQL语句（statement）</strong>，每一条对数据进行修改的SQL都会记录在日志文件中。主从复制的时候，从库（slave）会将日志解析为原文本，并在从库重新执行一次。</li>
</ul>
</li>
<li>row<ul>
<li>该日志格式在日志文件中<strong>记录的是每一行的数据变更</strong>，而不是记录SQL语句。主从复制的时候，从库对相同的数据进行修改</li>
</ul>
</li>
<li>mixed<ul>
<li>这是目前MySQL默认的日志格式，即混合了STATEMENT 和 ROW两种格式。默认情况下采用STATEMENT，但是在一些特殊情况下采用ROW来进行记录。MIXED格式能尽量利用两种模式的优点，而避开他们的缺点。</li>
</ul>
</li>
</ol>
<h4 id="（3）查询日志"><a href="#（3）查询日志" class="headerlink" title="（3）查询日志"></a>（3）查询日志</h4><p>查询日志中记录了<strong>客户端的所有操作语句</strong>，而<strong>二进制日志不包含查询数据</strong>的SQL语句。</p>
<h4 id="（4）慢查询日志"><a href="#（4）慢查询日志" class="headerlink" title="（4）慢查询日志"></a>（4）慢查询日志</h4><p>慢查询日志记录了所有执行时间超过参数 long_query_time 设置值并且扫描记录数不小于min_examined_row_limit的所有的SQL语句的日志。long_query_time 默认为 10 秒，最小为 0， 精度可以到微<br>秒。</p>
<h2 id="18-mysql复制"><a href="#18-mysql复制" class="headerlink" title="18.mysql复制"></a>18.mysql复制</h2><p>复制是指将主数据库的DDL（数据定义语言）和DML（数据操纵语言）操作通过<strong>二进制日志</strong>传到从库服务器中，然后在从库上对这些日志重新执行（也叫重做），从而使得从库和主库的数据保持同步。</p>
<p>MySQL支持一台主库同时向多台从库进行复制， 从库同时也可以作为其他从服务器的主库，实现链状复制。</p>
<p><strong>mysql的主从复制流程：</strong></p>
<p><img src="https://gitee.com/CyChan811/BlogImage/raw/master/img/20201007215457.png" alt=""><br>流程简述：</p>
<p>Master执行完增删改操作后都会记录binlog日志,当需要同步的时候会主动通知slave节点，slave收到通知后使用IO线程主动去master读取binlog写入relay日志(中转日志),然后使SQL线程完成对relay日志的解析然后入库操作,完成同步。</p>
<h2 id="19-事务还没执行完数据库挂了，重启的时候会发生什么？"><a href="#19-事务还没执行完数据库挂了，重启的时候会发生什么？" class="headerlink" title="19.事务还没执行完数据库挂了，重启的时候会发生什么？"></a>19.事务还没执行完数据库挂了，重启的时候会发生什么？</h2><p>在innoDB的存储引擎中，事务日志通过重做(redo)日志和innoDB存储引擎的日志缓冲(InnoDB Log Buffer)实现。事务开启时，<strong>事务中的操作，都会先写入存储引擎的日志缓冲中，在事务提交之前，这些缓冲的日志都需要提前刷新到磁盘上持久化</strong>，这就是DBA们口中常说的“<strong>日志先行</strong>”(Write-Ahead Logging)。</p>
<p>当事务提交之后，在Buffer Pool中映射的数据文件才会慢慢刷新到磁盘。此时如果数据库崩溃或者宕机，那么当系统重启进行恢复时，就可以根据redo log中记录的日志，把数据库恢复到崩溃前的一个状态。未完成的事务，可以继续提交，也可以选择回滚，这基于恢复的策略而定。</p>
<h2 id="20-undo日志和redo日志分别是干嘛的？"><a href="#20-undo日志和redo日志分别是干嘛的？" class="headerlink" title="20.undo日志和redo日志分别是干嘛的？"></a>20.undo日志和redo日志分别是干嘛的？</h2><h4 id="redo日志"><a href="#redo日志" class="headerlink" title="redo日志"></a>redo日志</h4><p>redo log重做日志是InnDB存储引擎层的，用来保证事务安全。在事务提交之前，每个修改操作都会记录在redo日志中，并被刷新到磁盘中持久化，保存的是物理日志。防止发生故障的时间点，有脏页未写入磁盘，在重启mysql的时候，根据redo log进行重做从而达到事务的持久性</p>
<p>在系统启动的时候，就已经为redo log分配了一块连续的存储空间,以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。所有的事务共享redo log的存储空间，它们的Redo Log按语句的执行顺序，依次交替的记录在一起。</p>
<h4 id="undo日志"><a href="#undo日志" class="headerlink" title="undo日志"></a>undo日志</h4><p>undo log主要为事务的回滚服务。在事务执行的过程中，除了记录redo log，还会记录一定量的undo log。undo log记录了数据在每个操作前的状态，如果事务执行过程中需要回滚，就可以根据undo log进行回滚操作。单个事务的回滚，只会回滚当前事务做的操作，并不会影响到其他的事务做的操作。</p>
<p><strong>redo log其实保障的是事务的持久性和一致性，而undo log则保障了事务的原子性。</strong></p>
<h2 id="21-mysql的MVCC的实现原理"><a href="#21-mysql的MVCC的实现原理" class="headerlink" title="21.mysql的MVCC的实现原理"></a>21.mysql的MVCC的实现原理</h2><p>MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能，用更好的方式去<strong>处理读-写冲突</strong>，<strong>做到即使有读写冲突时，也能做到不加锁，非阻塞并发读。</strong> 而这个读指的就是<strong>快照读</strong>, 而非当前读，当前读实际上是一种加锁的操作，是悲观锁的实现</p>
<p>MVCC 提供了时点（point in time）一致性视图。MVCC 并发控制下的读事务一般使用时间戳或者事务 ID去标记当前读的数据库的状态（版本），读取这个版本的数据。读、写事务相互隔离，不需要加锁。读写并存的时候，写操作会根据目前数据库的状态，创建一个新版本，并发的读则依旧访问旧版本的数据。</p>
<p><strong>MVCC(Multiversion concurrency control) 就是 同一份数据临时保留多版本的一种方式，使得读写操作没有冲突，进而实现并发控制</strong></p>
<h2 id="22-RC，RR级别下的InnoDB快照读有什么不同？"><a href="#22-RC，RR级别下的InnoDB快照读有什么不同？" class="headerlink" title="22.RC，RR级别下的InnoDB快照读有什么不同？"></a>22.RC，RR级别下的InnoDB快照读有什么不同？</h2><p><strong>快照读</strong>：读取的是记录数据的可见版本（可能是过期的数据），不用加锁，用MVCC解决脏读、不可重复读、幻读的问题；</p>
<p><strong>当前读：</strong> 读取的是记录数据的最新版本，并且当前读返回的记录都会加上锁，保证其他事务不会再并发的修改这条记录，使用行锁+间隙锁解决脏读、不可重复读和幻读的问题</p>
<p>正是Read View生成时机的不同，从而造成RC,RR级别下快照读的结果的不同</p>
<p>在RC隔离级别下，是每个快照读都会生成并获取最新的Read View；而在RR隔离级别下，则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View。</p>
<p><strong>什么是ReadVIew？</strong></p>
<p><strong>ReadVIew是记录当前系统中的所有的活跃事务的一个列表</strong>，这个数据结构中存储了当前Read View中最大的事务ID及最小的事务ID。</p>
<p>Read View不仅仅会通过一个列表trx_list来维护事务2执行快照读那刻系统正活跃的事务ID，还会有两个属性up_limit_id（<strong>记录trx_list列表中事务ID最小的ID</strong>），low_limit_id(<strong>记录快照读那刻系统尚未分配的下一个事务ID</strong>(目前已出现过的事务ID的最大值+1)) </p>
<h5 id="参考："><a href="#参考：" class="headerlink" title="参考："></a>参考：</h5><p><a href="https://zhuanlan.zhihu.com/p/64576887" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/64576887</a></p>
<p><a href="https://www.cnblogs.com/yulibostu/articles/11580136.html" target="_blank" rel="noopener">https://www.cnblogs.com/yulibostu/articles/11580136.html</a></p>
<h2 id="23-视图的作用？"><a href="#23-视图的作用？" class="headerlink" title="23.视图的作用？"></a>23.视图的作用？</h2><p>视图是一个虚拟表，是sql的查询结果，其内容由查询定义。同真实的表一样，视图包含一系列带有名称的列和行数据，在使用视图时动态生成。视图的数据变化会影响到基表，基表的数据变化也会影响到视图[insert update delete ] </p>
<p><strong>作用：</strong></p>
<ol>
<li>提高了重用性，对于频繁查询的数据可以生成一个视图；</li>
<li>对数据库重构，却不影响程序的运行，例如拆表的时候；</li>
<li>提高了安全性能。可以对不同的用户，设定不同的视图。</li>
<li>让数据更加清晰。想要什么样的数据，就创建什么样的视图。</li>
</ol>
<h2 id="24-存储引擎的选择"><a href="#24-存储引擎的选择" class="headerlink" title="24.存储引擎的选择"></a>24.存储引擎的选择</h2><ul>
<li>InnoDB : 是Mysql的默认存储引擎，用于事务处理应用程序，支持外键。如果应用<strong>对事务的完整性有比较高<br>的要求，在并发条件下要求数据的一致性，数据操作除了插入和查询意外，还包含很多的更新、删除操作</strong>，<br>那么InnoDB存储引擎是比较合适的选择。InnoDB存储引擎除了有效的降低由于删除和更新导致的锁定， 还<br>可以确保事务的完整提交和回滚，对于类似于计费系统或者财务系统等对数据准确性要求比较高的系统，<br>InnoDB是最合适的选择。</li>
<li>MyISAM ： 如果应用是<strong>以读操作和插入操作为主，只有很少的更新和删除操作，并且对事务的完整性、并发<br>性要求不是很高</strong>，那么选择这个存储引擎是非常合适的。</li>
</ul>
<h2 id="25-索引的优势和劣势"><a href="#25-索引的优势和劣势" class="headerlink" title="25.索引的优势和劣势"></a>25.索引的优势和劣势</h2><h4 id="优点："><a href="#优点：" class="headerlink" title="优点："></a>优点：</h4><ol>
<li>通过创建唯一性索引，可以保证数据库表中每一行数据的唯一性。</li>
<li>可以大大加快 数据的检索速度，这也是创建索引的最主要的原因。</li>
<li>可以加速表和表之间的连接，特别是在实现数据的参考完整性方面特别有意义。 </li>
<li>在使用分组和排序 子句进行数据检索时，同样可以显著减少查询中分组和排序的时间。 </li>
</ol>
<h4 id="缺点："><a href="#缺点：" class="headerlink" title="缺点："></a>缺点：</h4><ol>
<li>创建索引和维护索引要耗费时间，这种时间随着数据量的增加而增加。 </li>
<li>索引需要占物理空间，除了数据表占数据空间之外，每一个索引还要占一定的物理空间，如果要建立聚簇索引，那么需要的空间就会更大。 </li>
<li>当对表中的数据进行增加、删除和修改的时候，索引也要动态的维护，这样就降低了数据的更新速度。 </li>
</ol>
<h2 id="26-什么时候需要创建索引，什么时候不需要创建索引？"><a href="#26-什么时候需要创建索引，什么时候不需要创建索引？" class="headerlink" title="26.什么时候需要创建索引，什么时候不需要创建索引？"></a>26.什么时候需要创建索引，什么时候不需要创建索引？</h2><h4 id="什么时候需要创建索引"><a href="#什么时候需要创建索引" class="headerlink" title="什么时候需要创建索引"></a>什么时候需要创建索引</h4><ul>
<li>主键自动建立唯一索引</li>
<li>频繁作为查询条件的字段应该创建索引</li>
<li>查询中<strong>排序</strong>的字段创建索引将大大提高排序的速度（索引就是排序加快速查找</li>
<li>查询中<strong>统计或者分组</strong>的字段；</li>
</ul>
<h4 id="什么时候不需要创建索引"><a href="#什么时候不需要创建索引" class="headerlink" title="什么时候不需要创建索引"></a>什么时候不需要创建索引</h4><ul>
<li><strong>频繁更新</strong>的字段不适合创建索引，因为每次更新不单单是更新记录，还会更新索引，保存索引文件</li>
<li>where条件里用不到的字段，不创建索引；</li>
<li><strong>表记录太少</strong>，不需要创建索引；</li>
<li><strong>经常增删改</strong>的表；</li>
<li><strong>数据重复且分布平均的字段</strong>，因此为经常查询的和经常排序的字段建立索引。注意某些数据包含大量重复数据，因此他建立索引就没有太大的效果，例如性别字段，只有男女，不适合建立索引。</li>
</ul>
<h2 id="27-数据库主库和从库不一致，常见有这么几种优化方案？"><a href="#27-数据库主库和从库不一致，常见有这么几种优化方案？" class="headerlink" title="27.数据库主库和从库不一致，常见有这么几种优化方案？"></a>27.数据库主库和从库不一致，常见有这么几种优化方案？</h2><ol>
<li>业务可以接受，系统不优化</li>
<li>强制读主，高可用主库，用缓存提高读性能</li>
<li>在cache里记录哪些记录发生过写请求，来选择读主还是读从。缓存可以记录哪个库，哪个表，哪个主键三个信息刚发生过写操作，这条记录的超时时间，设置为“主从同步时延”</li>
</ol>
<h1 id="命令集合"><a href="#命令集合" class="headerlink" title="命令集合"></a>命令集合</h1><ul>
<li>show processlis：查看当前的状态</li>
<li>强制走索引的方式来查询<ul>
<li><code>select * from t force index(a) where c &lt; 100 and c &lt; 100000;</code></li>
</ul>
</li>
<li>查询索引的基数和实际是否符合<ul>
<li><code>show index from t;</code></li>
</ul>
</li>
<li>重新统计索引的基数<ul>
<li><code>analyze table t;</code></li>
</ul>
</li>
</ul>
<h4 id="—————————————-如有错误，欢迎指正！—————————————"><a href="#—————————————-如有错误，欢迎指正！—————————————" class="headerlink" title="—————————————-如有错误，欢迎指正！—————————————-"></a>—————————————-如有错误，欢迎指正！—————————————-</h4>
          
            <div class='article_footer'>
              
                
  
    
    



  

  
    
    



  

  
    
    

<section class="widget copyright  desktop mobile">
  <div class='content'>
    
      <blockquote>
        
          
            <p>本文由CyChan创作，转载请注明出处</p>

          
        
          
            <p>博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</p>

          
        
          
            <p>本文永久链接是：<a href=https://cychan811.gitee.io/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/>https://cychan811.gitee.io/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/</a></p>
          
        
      </blockquote>
    
  </div>
</section>

  

  
    
    

<section class="widget qrcode  desktop mobile">
  

  <div class='content article-entry'>
    
      
        <div class='fancybox'><img src='https://gitee.com/CyChan811/BlogImage/raw/master/img/20200704103702.png'
        
          height='128px'
        ></div>
      
    
  </div>
</section>

  


              
            </div>
          
        </div>
        
          


  <section class='meta' id="footer-meta">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date" itemprop="dateUpdated" datetime="2021-01-31T17:30:42+08:00">
  <a class='notlink'>
    <i class="fas fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：2021年1月31日</p>
  </a>
</div>

        
      
        
          
  
  <div class="new-meta-item meta-tags"><a class="tag" href="/tags/MySQL/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>MySQL</p></a></div>


        
      
        
          

        
      
        
          
  <div class="new-meta-item share -mob-share-list">
  <div class="-mob-share-list share-body">
    
      
        <a class="-mob-share-qq" title="" rel="external nofollow noopener noreferrer"
          
          href="http://connect.qq.com/widget/shareqq/index.html?url=https://cychan811.gitee.io/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/&title=mysql数据库笔记 - CyChan's Blog&summary=1.事务的ACID特性原子性(A)一个事务要么全部提交成功，要么全部失败回滚，不能只执行其中的一部分操作，这就是事务的原子性"
          
          >
          
            <img src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/logo/128/qq.png">
          
        </a>
      
    
      
        <a class="-mob-share-qzone" title="" rel="external nofollow noopener noreferrer"
          
          href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=https://cychan811.gitee.io/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/&title=mysql数据库笔记 - CyChan's Blog&summary=1.事务的ACID特性原子性(A)一个事务要么全部提交成功，要么全部失败回滚，不能只执行其中的一部分操作，这就是事务的原子性"
          
          >
          
            <img src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/logo/128/qzone.png">
          
        </a>
      
    
      
        <a class="-mob-share-weibo" title="" rel="external nofollow noopener noreferrer"
          
          href="http://service.weibo.com/share/share.php?url=https://cychan811.gitee.io/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/&title=mysql数据库笔记 - CyChan's Blog&summary=1.事务的ACID特性原子性(A)一个事务要么全部提交成功，要么全部失败回滚，不能只执行其中的一部分操作，这就是事务的原子性"
          
          >
          
            <img src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/logo/128/weibo.png">
          
        </a>
      
    
  </div>
</div>



        
      
    </div>
  </section>


        
        
          <div class="prev-next">
            
            
              <a class='next' href='/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/'>
                <p class='title'>计算机网络笔记<i class="fas fa-chevron-right" aria-hidden="true"></i></p>
                <p class='content'>1.POST和GET的区别
GET和POST本质上就是TCP链接，并无差别
GET，它用于获取信息，它只是获取、查询数据，也就是说它不会修改服务器上的数据，从这点来讲，它是数据安全的。例如获取更...</p>
              </a>
            
          </div>
        
      </section>
    </article>
  

  
    <!-- 显示推荐文章和评论 -->



  <article class="post white-box reveal comments shadow">
    <section class="article typo">
      <p ct><i class='fas fa-comments'></i> 评论</p>
      
      
      
      
      
      
        <section id="comments">
          <div id="valine_container" class="valine_thread">
            <i class="fas fa-cog fa-spin fa-fw fa-2x"></i>
          </div>
        </section>
      
      
    </section>
  </article>


  




<!-- 根据页面mathjax变量决定是否加载MathJax数学公式js -->



  <script>
    window.subData = {
      title: 'mysql数据库笔记',
      tools: true
    }
  </script>


</div>
<aside class='l_side'>
  
  

  
    
    



  <section class="widget toc-wrapper shadow desktop mobile" id="toc-div" >
    
  <header>
    
      <i class="fas fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-事务的ACID特性"><span class="toc-text">1.事务的ACID特性</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#原子性-A"><span class="toc-text">原子性(A)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#一致性-C"><span class="toc-text">一致性(C)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#隔离性-I"><span class="toc-text">隔离性(I)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#持久性-D"><span class="toc-text">持久性(D)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#注意："><span class="toc-text">注意：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-隔离级别"><span class="toc-text">2.隔离级别</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#事务的并发问题"><span class="toc-text">事务的并发问题</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Read-Uncommitted（读取未提交内容）"><span class="toc-text">Read Uncommitted（读取未提交内容）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Read-Committed（读取提交内容）"><span class="toc-text">Read Committed（读取提交内容）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Repeatable-Read（可重复读）"><span class="toc-text">Repeatable Read（可重复读）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Serializable（串行化）"><span class="toc-text">Serializable（串行化）</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-范式"><span class="toc-text">3.范式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#第一范式"><span class="toc-text">第一范式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#第二范式"><span class="toc-text">第二范式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#第三范式"><span class="toc-text">第三范式</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-聚集索引和非聚集索引、二级索引"><span class="toc-text">4.聚集索引和非聚集索引、二级索引</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-InnoDB为什么使用B-树做索引而不是使用B树"><span class="toc-text">5.InnoDB为什么使用B+树做索引而不是使用B树</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-为什么推荐自增id作为主键，而不是自建主键？"><span class="toc-text">6.为什么推荐自增id作为主键，而不是自建主键？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7-主键索引和普通索引，以及它们之间的区别"><span class="toc-text">7.主键索引和普通索引，以及它们之间的区别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-索引下推"><span class="toc-text">8.索引下推</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9-覆盖索引、联合索引"><span class="toc-text">9.覆盖索引、联合索引</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10-为什么用-B-树做索引而不用哈希表做索引？"><span class="toc-text">10.为什么用 B+ 树做索引而不用哈希表做索引？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#11-SQL注入漏洞产生的原因，如何防止？"><span class="toc-text">11.SQL注入漏洞产生的原因，如何防止？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#原因："><span class="toc-text">原因：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#防止措施："><span class="toc-text">防止措施：</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#12-explain之type"><span class="toc-text">12.explain之type</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-为什么MyISAM会比Innodb的查询速度快"><span class="toc-text">13.为什么MyISAM会比Innodb的查询速度快</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#14-缓存数据库和远程数据库怎么实现同步？"><span class="toc-text">14.缓存数据库和远程数据库怎么实现同步？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#15-mysql-innodb引擎什么时候表锁，什么时候行锁？"><span class="toc-text">15.mysql innodb引擎什么时候表锁，什么时候行锁？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#InnoDB基于索引的行锁"><span class="toc-text">InnoDB基于索引的行锁</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#行锁变表锁的情况："><span class="toc-text">行锁变表锁的情况：</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#16-行锁、间隙锁和next-key锁"><span class="toc-text">16.行锁、间隙锁和next-key锁</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#行锁"><span class="toc-text">行锁</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#间隙锁"><span class="toc-text">间隙锁</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#next-key锁"><span class="toc-text">next-key锁</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#注意"><span class="toc-text">注意</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#17-mysql日志"><span class="toc-text">17.mysql日志</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#（1）错误日志"><span class="toc-text">（1）错误日志</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#（2）二进制日志"><span class="toc-text">（2）二进制日志</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#（3）查询日志"><span class="toc-text">（3）查询日志</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#（4）慢查询日志"><span class="toc-text">（4）慢查询日志</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#18-mysql复制"><span class="toc-text">18.mysql复制</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#19-事务还没执行完数据库挂了，重启的时候会发生什么？"><span class="toc-text">19.事务还没执行完数据库挂了，重启的时候会发生什么？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#20-undo日志和redo日志分别是干嘛的？"><span class="toc-text">20.undo日志和redo日志分别是干嘛的？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#redo日志"><span class="toc-text">redo日志</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#undo日志"><span class="toc-text">undo日志</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#21-mysql的MVCC的实现原理"><span class="toc-text">21.mysql的MVCC的实现原理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#22-RC，RR级别下的InnoDB快照读有什么不同？"><span class="toc-text">22.RC，RR级别下的InnoDB快照读有什么不同？</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#参考："><span class="toc-text">参考：</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#23-视图的作用？"><span class="toc-text">23.视图的作用？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#24-存储引擎的选择"><span class="toc-text">24.存储引擎的选择</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#25-索引的优势和劣势"><span class="toc-text">25.索引的优势和劣势</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#优点："><span class="toc-text">优点：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#缺点："><span class="toc-text">缺点：</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#26-什么时候需要创建索引，什么时候不需要创建索引？"><span class="toc-text">26.什么时候需要创建索引，什么时候不需要创建索引？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#什么时候需要创建索引"><span class="toc-text">什么时候需要创建索引</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#什么时候不需要创建索引"><span class="toc-text">什么时候不需要创建索引</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#27-数据库主库和从库不一致，常见有这么几种优化方案？"><span class="toc-text">27.数据库主库和从库不一致，常见有这么几种优化方案？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#—————————————-如有错误，欢迎指正！—————————————"><span class="toc-text">—————————————-如有错误，欢迎指正！—————————————-</span></a></li></ol></li></ol></li></ol>
    </div>
  </section>


  


</aside>


  
  <footer class="clearfix">
    <br><br>
    
      
        <div class="aplayer-container">
          

  
    <meting-js
      theme='#1BCDFC'
      autoplay='false'
      volume='0.7'
      loop='all'
      order='random'
      fixed='false'
      list-max-height='340px'
      server='netease'
      type='playlist'
      id='2985312517'
      list-folded='true'>
    </meting-js>
  


        </div>
      
    
      
        <br>
        <div class="social-wrapper">
          
            
              <a href="mailto:1342736410@qq.com"
                class="social fas fa-envelope flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
            
              <a href="https://github.com/CyChan811"
                class="social fab fa-github flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
            
              <a href="http://wpa.qq.com/msgrd?v=3&amp;uin=1342736410&amp;site=qq&amp;menu=yes"
                class="social fab fa-qq flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
            
              <a href="http://music.163.com/playlist?id=2985312517&amp;userid=1980577201"
                class="social fas fa-headphones-alt flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
        </div>
      
    
      
        <div><p>博客内容遵循 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="noopener">署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</a></p>
        </div>
      
    
      
        本站使用
        <a href="https://volantis.js.org/" target="_blank" class="codename">volantis</a>
        作为主题，总访问量为
          <span id="busuanzi_value_site_pv"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span>
          次
      
    
      
        
      
    
      
      <br>
        <span id="timeDate"></span><span id="times"></span>
        <div class='copyright'>
          <a href="https://cychan811.gitee.io">Copyright © 2017-2020 CyChan</a>
        </div>
      
    
    
  </footer>


      <script>
      var now = new Date(); 
      function createtime() { 
          var grt= new Date("07/01/2020 12:00:00");//在此处修改你的建站时间，格式：月/日/年 时:分:秒
          now.setTime(now.getTime()+250); 
          days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); 
          hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); 
          if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); 
          mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;} 
          seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); 
          snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;} 
          document.getElementById("timeDate").innerHTML = "本站已安全运行 "+dnum+" 天 "+ hnum + " 小时 " + mnum + " 分 " + snum + " 秒"; 
      } 
        setInterval("createtime()",250);
     </script>
<script>setLoadingBarProgress(80);</script>


      <script>setLoadingBarProgress(60);</script>
    </div>
    <a class="s-top fas fa-arrow-up fa-fw" href='javascript:void(0)'></a>
  </div>
  
<script src="https://cdn.jsdelivr.net/npm/jquery@3.4/dist/jquery.min.js"></script>


  <script>
    
    var SEARCH_SERVICE = "hexo" || "hexo";
    var ROOT = "/" || "/";
    if (!ROOT.endsWith('/')) ROOT += '/';
  </script>





  <script async src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2/js/instant_page.js" type="module" defer integrity="sha384-OeDn4XE77tdHo8pGtE1apMPmAipjoxUQ++eeJa6EtJCfHlvijigWiJpD7VDPWXV1"></script>


  <script src="https://cdn.jsdelivr.net/npm/scrollreveal@4.0.6/dist/scrollreveal.min.js"></script>
  <script type="text/javascript">
    $(function() {
      ScrollReveal().reveal('.l_main .reveal', {
        distance: '8px',
        duration: '800',
        interval: '100',
        scale: '1'
      });
    });
  </script>


  
<script src="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.js"></script>

  <script type="text/javascript">
    $(function() {
      Waves.attach('.flat-btn', ['waves-button']);
      Waves.attach('.float-btn', ['waves-button', 'waves-float']);
      Waves.attach('.float-btn-light', ['waves-button', 'waves-float', 'waves-light']);
      Waves.attach('.flat-box', ['waves-block']);
      Waves.attach('.float-box', ['waves-block', 'waves-float']);
      Waves.attach('.waves-image');
      Waves.init();
    });
  </script>


  <script defer src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-busuanzi@2.3/js/busuanzi.pure.mini.js"></script>



  
  
  
    
<script src="https://cdn.jsdelivr.net/npm/jquery-backstretch@2.1.18/jquery.backstretch.min.js"></script>

    <script type="text/javascript">
      $(function(){
        var imgs=["https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg", "https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/BBC19066-E176-47C2-9D22-48C81EE5DF6B.jpeg", "https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/B18FCBB3-67FD-48CC-B4F3-457BA145F17A.jpeg", "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3799510479,4073126189&fm=26&gp=0.jpg", "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2883764232,1534773763&fm=26&gp=0.jpg", "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593783783483&di=3ad7e4713031f3e60c3a8bab2c2aae02&imgtype=0&src=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com%2F20191015%2F7d47db92bbe2627ecd035976a61463cb_00001.jpg", "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593783631802&di=0616aa53378b2de7816f786a97c75bfe&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F2018-01-10%2F5a55c62f9a142.jpg", "https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/00E0F0ED-9F1C-407A-9AA6-545649D919F4.jpeg", "https://cdn.jsdelivr.net/gh/zyoushuo/Blog/images/bj1.jpg", "https://gitee.com/CyChan811/BlogImage/raw/master/img/1 (2).png", "https://gitee.com/CyChan811/BlogImage/raw/master/img/t01e2fa7120d00d62da.jpg", "https://gitee.com/CyChan811/BlogImage/raw/master/img/1 (19).jpg"];
        if ('true' == 'true') {
          function shuffle(arr){
            /*From countercurrent-time*/
            var n = arr.length;
            while(n--) {
              var index = Math.floor(Math.random() * n);
              var temp = arr[index];
              arr[index] = arr[n];
              arr[n] = temp;
            }
          }
          shuffle(imgs);
        }
        if ('') {
          $('').backstretch(
            imgs,
          {
            duration: "20000",
            fade: "1500"
          });
        } else {
          $.backstretch(
            imgs,
          {
            duration: "20000",
            fade: "1500"
          });
        }
      });
    </script>
  



  
    
<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.js"></script>

  
    
<script src="https://cdn.jsdelivr.net/npm/meting@2.0/dist/Meting.min.js"></script>

  









  
    
<script src="https://cdn.jsdelivr.net/gh/HCLonely/Valine@latest/dist/Valine.min.js"></script>

  
  <script>
  var GUEST_INFO = ['nick','mail','link'];
  var meta = 'nick,mail,link'.split(',').filter(function(item){
    return GUEST_INFO.indexOf(item) > -1
  });
  var REQUIRED_FIELDS = ['nick','mail','link'];
  var requiredFields = 'nick,mail'.split(',').filter(function(item){
    return REQUIRED_FIELDS.indexOf(item) > -1
  });
  var valine = new Valine();
  var master = 'f03ef4cd1728b39a2b1d24cb0c7c4ac8'.split(',');
  function emoji(path, idx, ext) {
      return path + "/" + path + "-" + idx + "." + ext;
  }
  var emojiMaps = {};
  for (var i = 1; i <= 54; i++) {
    emojiMaps['tieba-' + i] = emoji('tieba', i, 'png');
  }
  for (var i = 1; i <= 101; i++) {
    emojiMaps['qq-' + i] = emoji('qq', i, 'gif');
  }
  for (var i = 1; i <= 116; i++) {
    emojiMaps['aru-' + i] = emoji('aru', i, 'gif');
  }
  for (var i = 1; i <= 125; i++) {
    emojiMaps['twemoji-' + i] = emoji('twemoji', i, 'png');
  }
  for (var i = 1; i <= 4; i++) {
    emojiMaps['weibo-' + i] = emoji('weibo', i, 'png');
  }
  valine.init({
    el: '#valine_container',
    meta: meta,
    
    appId: "COclWTHE9FOx0Kp5LQxypRuw-gzGzoHsz",
    appKey: "IFkkcvnaeUWqUUYoWqCJ5hUY",
    placeholder: "ヾﾉ≧∀≦)o来啊，快活啊!~",
    pageSize:'10',
    avatar:'robohash',
    lang:'zh-cn',
    visitor: 'true',
    highlight: 'true',
    mathJax: 'false',
    enableQQ: 'true',
    requiredFields: requiredFields,
    emojiCDN: 'https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/emoji/valine/',
    emojiMaps: emojiMaps,
    master: master
  })
  </script>





  
<script src="/js/app.js"></script>



  
<script src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2.6.5/js/search.js"></script>



  
<script src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2/js/comment_typing.js"></script>






<!-- 复制 -->

  <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="fas fa-copy"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('fa-copy');
        $icon.addClass('fa-check-circle');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('fa-check-circle');
          $icon.addClass('fa-copy');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('fa-copy');
        $icon.addClass('fa-times-circle');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('fa-times-circle');
          $icon.addClass('fa-copy');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>




<!-- fancybox -->
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>
<script>
  function pjax_fancybox() {
    $(".article-entry").find("img").not('.inline').not('a img').each(function () { //渲染 fancybox
      var element = document.createElement("a"); // a 标签
      $(element).attr("pjax-fancybox", "");  // 过滤 pjax
      $(element).attr("href", $(this).attr("src"));
      if ($(this).attr("data-original")) {
        $(element).attr("href", $(this).attr("data-original"));
      }
      $(element).attr("data-fancybox", "images");
      var caption = "";   // 描述信息
      if ($(this).attr('alt')) {  // 标准 markdown 描述信息
        $(element).attr('data-caption', $(this).attr('alt'));
        caption = $(this).attr('alt');
      }
      var div = document.createElement("div");
      $(div).addClass("fancybox");
      $(this).wrap(div); // 最外层套 div ，其实主要作用还是 class 样式
      var span = document.createElement("span");
      $(span).addClass("image-caption");
      $(span).text(caption); // 加描述
      $(this).after(span);  // 再套一层描述
      $(this).wrap(element);  // 最后套 a 标签
    })
    $(".article-entry").find("img").fancybox({
      selector: '[data-fancybox="images"]',
      hash: false,
      loop: false,
      closeClick: true,
      helpers: {
        overlay: {closeClick: true}
      },
      buttons: [
        "zoom",
        "close"
      ]
    });
  };
  $(function () {
    pjax_fancybox();
  });
</script>





  <script>setLoadingBarProgress(100);</script>
  <script src="https://cdn.jsdelivr.net/gh/zyoushuo/Blog/hexo/js/mouse_click.js"></script>
</body>
</html>
